/*
 * minet.h
 *
 *  Created on: 2019年4月27日
 *      Author: 0yfj0
 */

#ifndef _MINET_H_
#define _MINET_H_
#ifdef __cplusplus
extern "C"
{
#endif  /* __cplusplus */
#include <stdint.h>
#include <sys.h>
#include "minet_conf.h"

/*----------------------------------------------------------------------------*/
#define MINET_ADDR_GW		( 0x0000 )/* 网关地址 */
#define MINET_ADDR_ALL		( 0xffff )/* 广播地址 */
#define MINET_FLEN_MIN		( 1+1+1+4+0+1+1 )/* 最小帧长度 */
#define MINET_PINGDATA_LEN	( 4 )/* ping data数据长度 */
/*
 * flen(1byte)|seq(1byte)|ctrl(1byte)|dest(2byte) source(2byte) ...|[payload(n byte)]|sign(1byte)|crc8(1byte)
 *
 * flen 帧长度包括CRC字段
 *
 * ctrl 2:0 中继次数
 * ctrl 5:3 帧类型
 * 	0-announce，仅网关直接产生此帧，中继转发
 * 	1-ping
 * 	2-data
 * 	3-acknowledge
 * 	4/5/6/7-reserve
 * ctrl 6 是否需要中继，0-无需中继/1-需要中继
 * ctrl 7 保留
 *
 * sign 签名字段前所有数据计算签名
 *
 * crc8 校验字段前所有数据
 *
 * 网关地址 0x00 0x00
 * 广播地址 0xff 0xff
 *
 * announce
 * 	---- ---- 0x40 0xff 0xff 0x00 0x00 ---- ----
 * 	---- ---- 0x41 0xff 0xff 0x13 0x14 0x00 0x00 ---- ----
 * ping
 *  ---- ---- 0x08 0x00 0x00 0x11 0x11 data ---- ----
 *  ---- ---- 0x09 0x00 0x00 0x13 0x14 0x11 0x11 data ---- ----
 *  ---- ---- 0x48 0x00 0x00 0x11 0x11 data ---- ----
 *  ---- ---- 0x49 0x00 0x00 0x13 0x14 0x11 0x11 data ---- ----
 *  ping data
 *   flag(1byte)|err_frame(1byte)|err_crc(1byte)|err_sign(1byte)
 *   ping data.flag
 *    0-relay 此结点是否开启中继功能
 *
 * data
 *  ---- ---- 0x10 0x00 0x00 0x11 0x11 ... ---- ----
 *  ---- ---- 0x11 0x00 0x00 0x13 0x14 0x11 0x11 ... ---- ----
 *  ---- ---- 0x50 0x00 0x00 0x11 0x11 ... ---- ----
 *  ---- ---- 0x51 0x00 0x00 0x13 0x14 0x11 0x11 ... ---- ----
 *  acknowledge
 *  ---- ---- 0x18 0x00 0x00 0x11 0x11 ---- ----
 *  ---- ---- 0x19 0x00 0x00 0x13 0x14 0x11 0x11 ---- ----
 *  ---- ---- 0x58 0x00 0x00 0x11 0x11 ---- ----
 *  ---- ---- 0x59 0x00 0x00 0x13 0x14 0x11 0x11 ---- ----
 *
 * */

#define MINET_FTYP_ANN 		( 0 )//announce
#define MINET_FTYP_PING		( 1 )//ping
#define MINET_FTYP_DATA		( 2 )//data
#define MINET_FTYP_ACK		( 3 )//acknowledge

typedef struct
{
	uint16_t addr;
	uint8_t *buf;
	uint16_t len;
} minet_msg_t;

#if (MINET_GATEWAY)
typedef struct minet_node
{
	uint16_t dest;
	uint16_t hops;
	uint8_t pingdat[MINET_PINGDATA_LEN];
	uint32_t stamp;
	struct minet_node *next;
} minet_node_t;
#endif

typedef struct
{
	int nbus;/* 模块总线编号 */
	int nid;/* 网络ID */
	uint16_t addr;/* 本机地址 */
	uint16_t chl :8;/* 无线信道 */
#if (MINET_NODE)
	uint16_t regchl :8;/* 注册网络信道 0-正在注册 */
	uint16_t direct :1;/* 与网关直连 */
	uint16_t rping :2;/* ping重试 */
	int rssi;/* 与网关连接（直连/中继）的rssi */
#endif
	uint16_t seq :8;
	uint16_t lflag :3;/* 循环事务处理类型标记 */

#define MINET_ACK_MAX 4
#if (MINET_ACK_SZ>0 && MINET_ACK_SZ<MINET_ACK_MAX)
	minet_msg_t *ackfifo[MINET_ACK_SZ];
#elif MINET_ACK_SZ<=0 && MINET_ACK_SZ>=MINET_ACK_MAX
#error MINET_ACK_SZ must 1-(MINET_ACK_MAX-1)
#endif

#define MINET_RELAY_MX 4
#if (MINET_RELAY_SZ>0 && MINET_RELAY_SZ<MINET_RELAY_MX)
	uint16_t relay :1;/* 启用中继 */
	minet_msg_t *rlfifo[MINET_RELAY_SZ];
#elif MINET_RELAY_SZ<0 && MINET_RELAY_SZ>=MINET_RELAY_MX
#error MINET_RELAY_SZ must 0-(MINET_RELAY_MX-1)
#endif

#define MINET_RXFIFO_MX 4
#if (MINET_RXFIFO_SZ>0 && MINET_RXFIFO_SZ<MINET_RXFIFO_MX)
	minet_msg_t *rxfifo[MINET_RXFIFO_SZ];
#elif MINET_RXFIFO_SZ<=0 && MINET_RXFIFO_SZ>=MINET_RXFIFO_MX
#error MINET_RXFIFO_SZ must 0-(MINET_RXFIFO_MX-1)
#endif

	uint8_t tpnet;/* 暂停入网间隔/分，announce间隔/秒 */
	uint32_t tnet;/* 暂停入网时间，ping时间，announce时间 */

#if (MINET_GATEWAY)
	minet_node_t *nlis;
	uint16_t nodes;
#endif

	struct
	{
		uint8_t frame;/* 帧错误 */
		uint8_t fcrc;/* 帧CRC校验错误 */
		uint8_t fsign;/* 帧签名错误 */

#if (MINET_GATEWAY)
		uint8_t conflict;/* gateway conflict */
#endif
#if (MINET_NODE)
		uint8_t pnoack;/* node ping noack */
#endif
	} err;
} minet_if_t;

int minet_init(minet_if_t *nif, int nbus, int netid, uint16_t addr, uint8_t chl);
int minet_relay(minet_if_t *nif, int relay);
int minet_ping(minet_if_t *nif, uint16_t dest, int tout);
#if (MINET_NODE)
int minet_rssi(minet_if_t *nif);
#endif
int minet_clear(minet_if_t *nif);
int minet_send(minet_if_t *nif, minet_msg_t *msg);
int minet_ack_wait(minet_if_t *nif, int tout);
minet_msg_t *minet_recv(minet_if_t *nif);
void minet_loop_task(minet_if_t *nif);

/*----------------------------------------------------------------------------*/
/* 在minet_hal.c实现 */
void minet_hal_wdt_feed(void);
uint32_t minet_hal_tick1s(void);
uint32_t minet_hal_random(void);

int minet_hal_init(minet_if_t *nif);
int minet_hal_rssi(minet_if_t *nif);
int minet_hal_chl(minet_if_t *nif, int chl);
int minet_hal_cd(minet_if_t *nif);
int minet_hal_write(minet_if_t *nif, void *buf, int len);
int minet_hal_read(minet_if_t *nif, void *buf, int sz);

/* 在minet_utils.c实现 */
uint8_t minet_sign(uint8_t nid, uint8_t *buf, int len);
uint8_t minet_crc8(uint8_t *buf, int len);

minet_msg_t *minet_msg_malloc(int sz);
void minet_msg_free(minet_msg_t *ptr);
#if (MINET_GATEWAY)
minet_node_t *minet_node_alloc(uint16_t dest, int hops, uint8_t *pingdat);
//void minet_node_free(minet_node_t *ptr);
#define minet_node_free(ptr) minet_msg_free((minet_msg_t*)ptr)
#endif

/*----------------------------------------------------------------------------*/
#if (MINET_NODEMAX<=0||MINET_NODEMAX>65535)
#error MINET_NODEMAX [1-65535]
#endif
#if (MINET_T1S_ANN<3)
#error MINET_T1S_ANN [3-]
#endif
#if (MINET_T1S_PING<3)
#error MINET_T1S_PING [3-]
#endif
#if (MINET_FLEN_MAX<MINET_FLEN_MIN)
#error MINET_FLEN_MAX [MINET_FLEN_MIN-]
#endif
#if (MINET_NEXTCHL_EMIN<3||MINET_NEXTCHL_EMIN>100)
#error MINET_NEXTCHL_EMIN [3-100]
#endif
#if (MINET_PNOACK_REGCHL<=0 || MINET_PNOACK_REGCHL>60)
#error MINET_PNOACK_REGCHL [1-60]
#endif

#ifdef __cplusplus
}
#endif  /* __cplusplus */
#endif /* _MINET_H_ */
